package com.suray.wcs.service.plc;

import com.suray.basic.wcs.plc.core.Plc;
import com.suray.basic.wcs.plc.oper.PlcOper;
import com.suray.basic.wcs.plc.oper.impl.PlcOperImpl;
import com.suray.basic.wcs.plc.pojo.oper.ShapeDetectorOper;
import com.suray.basic.wcs.plc.pojo.oper.SweepCodeEquipmentOper;
import com.suray.basic.wcs.plc.pojo.oper.WeightingEquipmentOper;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.commin.enmus.DeviceStatus;
import com.suray.system.run.ding.DingRobot;
import com.suray.wcs.service.config.properties.WcsProperties;
import com.suray.wcs.service.core.util.DateUtil;
import com.suray.wcs.service.enums.NotificationTypeEnum;
import com.suray.wcs.service.init.SystemInit;
import com.suray.wcs.service.system.entity.PortDB;
import com.suray.wcs.service.system.service.IWareHouseDBService;
import com.suray.wcs.service.system.service.impl.WareHouseDBServiceImpl;
import com.suray.wcs.service.util.WcsUtil;
import com.suray.wcs.service.wmsconnect.TaskApply;
import com.suray.wcs.service.wmsconnect.ToWMSImpl;
import com.suray.wcs.service.wmsconnect.WmsResponses;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.util.Date;

public class NormalBarCodeScanner {

    @Autowired
    private static IWareHouseDBService wareHouseDBService = SpringContextHolder.getBean(WareHouseDBServiceImpl.class);
    private static ToWMSImpl toWMS = SpringContextHolder.getBean(ToWMSImpl.class);
    private static Logger log = LoggerFactory.getLogger(BarCodeScanner.class);

    public static void start(PortDB port) {
        PortDB realPort = SystemInit.PORTS.get(port.getPortId());
        //称重
        WeightingEquipmentOper weightingEquipmentOper = (WeightingEquipmentOper) Plc.deviceBaseNameMap.get(realPort.getWeightName() == null ? "" : realPort.getWeightName());
        //扫码
        SweepCodeEquipmentOper sweepCodeEquipmentOper = (SweepCodeEquipmentOper) Plc.deviceBaseNameMap.get(realPort.getScanName() == null ? "" : realPort.getScanName());
        //外形检测
        ShapeDetectorOper shapeDetectorOper = (ShapeDetectorOper) Plc.deviceBaseNameMap.get(realPort.getShapeName() == null ? "" : realPort.getShapeName());
        PlcOper plcOper;
        try {
            double weightData = 0;
            String barCode;
            int heightType = 0;
            TaskApply taskApply = new TaskApply();
            if (sweepCodeEquipmentOper != null && sweepCodeEquipmentOper.isCanRead()) {
                plcOper = PlcOperImpl.getPlcOper(sweepCodeEquipmentOper.getPlc());
                barCode = sweepCodeEquipmentOper.getCodeData();
                log.info("{}_barCode:{}", sweepCodeEquipmentOper.getDeviceName(), barCode);
                if (weightingEquipmentOper != null) {
                    weightData = weightingEquipmentOper.getWeightData();
                    log.info("{}_weightData:{}", weightingEquipmentOper.getDeviceName(), weightData);
                    boolean isCanRead = weightingEquipmentOper.isCanRead();
                    if (!isCanRead) {
                        sendPlcBack(realPort, plcOper, sweepCodeEquipmentOper, shapeDetectorOper,
                                weightingEquipmentOper,
                                realPort.getPortName() + "," + weightingEquipmentOper.getDeviceName() + "不可读");
                        return;
                    }
                }
                if (shapeDetectorOper != null) {
                    heightType = shapeDetectorOper.getHighType();
                    log.info("{}_heightType:{}", shapeDetectorOper.getDeviceName(), heightType);
                    int shapeResult = shapeDetectorOper.getResult();
                    if (shapeResult != 1) {
                        StringBuilder stringBuilder = new StringBuilder("外形检测不合格,外形检测结果:");
                        if (shapeDetectorOper.isHighTransfinite()) {
                            stringBuilder.append("超高！");
                        }
                        if (shapeDetectorOper.isFrontTransfinite()) {
                            stringBuilder.append("前超限！");
                        }
                        if (shapeDetectorOper.isAfterTransfinite()) {
                            stringBuilder.append("后超限！");
                        }
                        if (shapeDetectorOper.isLeftTransfinite()) {
                            stringBuilder.append("左超限！");
                        }
                        if (shapeDetectorOper.isRightTransfinite()) {
                            stringBuilder.append("右超限！");
                        }
                        sendPlcBack(realPort, plcOper, sweepCodeEquipmentOper, shapeDetectorOper,
                                weightingEquipmentOper,
                                realPort.getPortName() + "," + stringBuilder);
                        return;
                    }
                    if (heightType == 0 || heightType > 3) {
                        sendPlcBack(realPort, plcOper, sweepCodeEquipmentOper, shapeDetectorOper,
                                weightingEquipmentOper,
                                realPort.getPortName() + "," +
                                        shapeDetectorOper.getDeviceName() + "高度类型错误：" + heightType);
                        return;
                    }
                }
                boolean equals = wareHouseDBService.getCurWareHouseDB().getStatus().equals(DeviceStatus.DISABLE.getCode());

                taskApply.setCargoWeight(weightData);
                taskApply.setBarCode(barCode.trim());//清除空格
                taskApply.setCargoHeight(heightType);
                taskApply.setApplyTime(DateUtil.format(new Date(), DateUtil.YMDHMS));
                taskApply.setFromPort(realPort.getPortCode());
                // 未联机或者申请成功   ||
                WmsResponses wmsResponses = null;
                if (!equals) {
                    wmsResponses = toWMS.exeTaskApply(taskApply);
                }
                if (equals || wmsResponses.getReturnStatus() == WcsProperties.SUCCESS) {
                    if (equals) {
                        log.info("{}单机模式默认成功", realPort.getPortName());
                        DingRobot.pauseMessage(realPort.getPortName() + "单机模式默认成功,等待手动下发任务！");
                    } else {
                        log.info("{}读取条码后，请求WMS成功", realPort.getPortName());
                    }
                    try {
                        plcOper.readComplete(sweepCodeEquipmentOper.getDeviceNo(), true);
                        plcOper.dataEligible(sweepCodeEquipmentOper.getDeviceNo(), true);
                        while (sweepCodeEquipmentOper.isCanRead()) {
                            Thread.sleep(1000);
                        }
                    } catch (IOException e) {
                        log.warn("{}向电控发送读取完成信号失败", realPort.getPortName(), e);
                    } catch (Exception e) {
                        log.warn("{}任务申请失败后，后续逻辑错误！", realPort.getPortName(), e);
                    }
                } else {
                    log.info("{}读取条码后，请求WMS失败", realPort.getPortName());
                    sendPlcBack(realPort, plcOper, sweepCodeEquipmentOper, shapeDetectorOper, weightingEquipmentOper,
                            realPort.getPortName() + wmsResponses.getReturnInfo() + ":" + barCode);
                }
            }
        } catch (Exception e) {
            WcsUtil.notification(realPort.getPortName() + "称重、扫码、外形检测出现异常", NotificationTypeEnum.ERROR);
            log.warn(realPort.getPortName() + "称重、扫码、外形检测出现异常:{}", e);
        }
    }

    private static void sendPlcBack(PortDB port, PlcOper plcOper, SweepCodeEquipmentOper sweepCodeEquipmentOper,
                                    ShapeDetectorOper shapeDetectorOper, WeightingEquipmentOper weightingEquipmentOper,
                                    String message) {
        try {
            LoggerUtil.info(message, NormalBarCodeScanner.class);
            clearDeviceData(sweepCodeEquipmentOper, shapeDetectorOper, weightingEquipmentOper, plcOper);
            plcOper.dataEligible(sweepCodeEquipmentOper.getDeviceNo(), false);

            WcsUtil.notification(message);
        } catch (IOException e) {
            log.warn("{}向电控发送读取完成信号失败", port.getPortName(), e);
        } catch (Exception e) {
            log.warn("回退逻辑错误！", port.getPortName(), e);
        }
    }

    private static void clearDeviceData(SweepCodeEquipmentOper sweepCodeEquipmentOper, ShapeDetectorOper shapeDetectorOper,
                                        WeightingEquipmentOper weightingEquipmentOper, PlcOper plcOper) throws IOException {
        if (shapeDetectorOper != null) {
            plcOper.readComplete(shapeDetectorOper.getDeviceNo(), true);
        }

        if (weightingEquipmentOper != null) {
            plcOper.readComplete(weightingEquipmentOper.getDeviceNo(), true);
        }

        plcOper.readComplete(sweepCodeEquipmentOper.getDeviceNo(), true);
    }
}
